using System;
using System.Collections.Generic;
using System.Text;

using Sandia.MVCFramework.Common;
using Sandia.MVCFramework.Data;
using Sandia.MVCFramework.Request;
using Sandia.MVCFramework.Plugin;

namespace Sandia.MVCFramework.DataAnalyzer
{
    /// <summary>
    /// Abstract standard implementation of a data analyzer
    /// </summary>
    public abstract class AbstractStandardDataAnalyzer: IDataAnalyzer
    {
        /// <summary>
        /// The publisher used by this data analyzer
        /// </summary>
        protected IPublisher publisher;

        /// <summary>
        /// The request router used by this data analyzer
        /// </summary>
        protected IRequestRouter requestRouter;

        /// <summary>
        /// The parent plugin of this data accessor.
        /// </summary>
        protected IPlugin plugin;

        /// <summary>
        /// Whether or not this item has already been disposed
        /// </summary>
        private bool disposed = false;

        #region ISubscriber Members

        /// <summary>
        /// The list of IData types that this subscriber would like to subscribe
        /// to.
        /// </summary>
        public abstract IList<Type> DesiredSubscriptions
        {
            get;
        }

        /// <summary>
        /// Method for receiving and handling published data
        /// </summary>
        /// <param name="dataPacket">
        /// The data packet that was published.
        /// </param>
        public abstract void HandlePublishedData(DataPacket dataPacket);

        /// <summary>
        /// Whether or not this object has been disposed
        /// </summary>
        public bool IsDisposed
        {
            get { return disposed; }
        }

        /// <summary>
        /// To be called when disposing
        /// </summary>
        public event EventHandler Disposed;

        #endregion

        #region IRequestProcessor Members

        /// <summary>
        /// The IRequest types that this RequestProcessor would like to process.
        /// </summary>
        public abstract IList<Type> DesiredRequests
        {
            get;
        }

        /// <summary>
        /// Processes an incoming request
        /// </summary>
        /// <remarks>The request is an object (and not an IRequest) in
        /// order to match the function signature for dispatching threads
        /// in a thread pool; checking is provided in the classes that
        /// process requests to make sure they are actually IRequests</remarks>
        /// <param name="request">The IRequest to process</param>
        protected abstract void processRequest(IRequest request);

        /// <summary>
        /// Processes an incoming request
        /// </summary>
        public void ProcessRequest(IRequest request)
        {
            try
            {
                this.processRequest((IRequest)request);
            }
            catch (Exception e)
            {
                // Generate a log entry
                LoggingTools.SendToLog(
                    "AbstractStandardDataAccessor.ProcessRequest: Unable to process request\n " + e.Message,
                    LoggingCategories.ERROR,
                    100);
            }
        }

        #endregion

        #region IDataPacketProducer Members

        /// <summary>
        /// Initialize the data packet producer by telling
        /// it who publishes the data packets produced
        /// </summary>
        /// <param name="publisher">The publisher for data
        /// packets produced</param>
        public void InitDataPacketProducer(
            IPublisher publisher)
        {
            this.publisher = publisher;
        }

        #endregion

        #region IRequestGenerator Members

        /// <summary>
        /// Initialize the request generator by telling
        /// it who routes the requests produced
        /// </summary>
        /// <param name="requestRouter">The router for requests
        /// generated</param>
        public void InitRequestGenerator(
            IRequestRouter requestRouter)
        {
            this.requestRouter = requestRouter;
        }

        #endregion

        #region IDisposable Members

        /// <summary>
        /// Clean up all managed and unmanaged resources
        /// used by object
        /// </summary>
        public virtual void Dispose()
        {
            disposed = true;
            if (Disposed != null) Disposed(this, new EventArgs());
        }

        #endregion

        #region IStartable Members

        /// <summary>
        /// Called when MVC Framework initialization has completed and
        /// transactions can begin.
        /// </summary>
        /// <remarks>
        /// IRequests and IData should not be sent before this method is called, 
        /// as this can cause race conditions while an application is 
        /// initializing.
        /// </remarks>
        public abstract void Start();

        #endregion

        #region IPluginComponent Members

        /// <summary>
        /// Initializes the plugin component.
        /// </summary>
        /// <param name="plugin">The component's parent plugin.</param>
        public void InitPluginComponent(
            IPlugin plugin)
        {
            this.plugin = plugin;
        }

        #endregion
    }
}
